namespace twoDMatrixLibrary
{
    using System;
    using System.IO;
    using System.Globalization;

    public class Vector
    {
        private Matrix Data;
        private int Dimensions;

        # region "Constructors"
        public Vector(int Dimensions)
        {
            this.Data = new Matrix(Dimensions, 1);
            this.Dimensions = Dimensions;
        }

        public Vector(int Dimensions, double value)
        {
            this.Dimensions = Dimensions;
            this.Data = new Matrix(Dimensions, 1);

            for (int i = 0; i < this.Dimensions; i++)
                this.Data[i, 0] = value;
        }
        public Vector(Matrix m)
        {
            this.Dimensions = m.Rows;
            this.Data = new Matrix(Dimensions, 1);
            this.Data = m;
        }
        public Vector(Vector v)
        {
            this.Dimensions = v.NumberOfDimensions;
            this.Data = new Matrix(Dimensions, 1);
            for (int i = 0; i < this.Dimensions; i++)
                this.Data[i, 0] = v[i];
        }
        public Vector(double[] values)
        {
            this.Dimensions = values.Length;
            this.Data = new Matrix(Dimensions, 1);
            for (int i = 0; i < this.Dimensions; i++)
                this.Data[i, 0] = values[i];
        }

        # endregion

        public override bool Equals(object obj)
        {
            return Equals(this, (Vector)obj);
        }

        public static bool Equals(Vector left, Vector right)
        {
            if (((object)left) == ((object)right))
            {
                return true;
            }

            if ((((object)left) == null) || (((object)right) == null))
            {
                return false;
            }

            if ((left.Dimensions != right.Dimensions))
            {
                return false;
            }

            for (int i = 0; i < left.Dimensions; i++)
            {
                if (left.Data[i, 0] != right.Data[i, 0])
                    {
                        return false;
                    }
                
            }

            return true;
        }

        public override int GetHashCode()
        {
            return (this.Data.Rows + this.Data.Columns);
        }

        public int NumberOfDimensions
        {
            get
            {
                return this.Dimensions;
            }
        }

        public double this[int d]
        {
            set
            {
                Data[d,0] = value;
            }

            get
            {
                return Data[d,0];
            }
        }

        public Vector Clone()
        {
            Vector temp = new Vector(this.Data);
            return temp;
        }

        public Matrix DataTranspose()
        {
            return this.Data.Transpose();
        }

        public Double AbsoluteLength()
        {
            return this.Data.FrobeniusNorm;
        }

        public Vector UnitVector()
        {
            return new Vector(this.Dimensions, 1);
        }

        public static bool operator ==(Vector left, Vector right)
        {
            return Equals(left.Data, right.Data);
        }

        public static bool operator !=(Vector left, Vector right)
        {
            return !Equals(left.Data, right.Data);
        }

        public static Vector operator +(Vector left, Vector right)
        {
            return new Vector(left.matrix + right.matrix);
          }

        public Matrix matrix
        {
            get
            {
                return this.Data;
            }
            set
            {
                this.Data = value;
            }
        }
        public static Vector operator -(Vector left, Vector right)
        {
            Vector temp = new Vector(left.Data - right.Data);
            return temp;
        }
        public static Vector operator *(Vector left, double right)
        {
            Vector temp = new Vector(left.Data * right);
            return temp; 
        }

        public static Vector operator *(Vector left, Vector right)
        {
             Vector temp = new Vector(left.Data * right.Data);
            return temp;
        }
        public static Vector operator /(Vector left, double value  )
        {
            return new Vector(left.Data * (1 / value));
        }

        public static bool operator >(Vector left, Vector right)
        {
            for (int i = 0; i < left.NumberOfDimensions; i++)
                if (left[i] < right[i])
                    return false;

            return true;
         }
        public static bool operator <(Vector left, Vector right)
        {
            for (int i = 0; i < left.NumberOfDimensions; i++)
                if (left[i] > right[i])
                    return false;

            return true;
        }

        public Vector NormalizedForm()
        {
            double length = this.Data.FrobeniusNorm;
            Vector temp = new Vector(this.Data * (1 / length ));
            return temp;
        }
        public void Dispose()
        {
            this.Data = null;
            this.Dimensions = 0;
        }
        public override string  ToString()
{
    
        string value =  "[";
        for (int i = 0; i < this.Dimensions; i++)
            value = value + " " + this[i] + " ";
        value = value + "]";

        return value;
}
     
    }
}



